package com.yirui.bridge.tcp.server;

import com.yirui.bridge.core.Server;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.CharsetUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.buf.HexUtils;
import org.springframework.boot.ApplicationArguments;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * tcp监听服务，用于某些需要固定端口数据转发
 * @author Dujie
 * @create 2025/7/23
 * @since 1.0.0
 */
@Slf4j
public class AgentServer implements Server {
    private Channel channel;
    private EventLoopGroup bossGroup;
    private EventLoopGroup workerGroup;

    private Map<String,Channel > ipTables = new ConcurrentHashMap<>();
    /**
     *
     * @param port
     * @throws Exception
     */
    public void start(int port) throws Exception {
        // 创建EventLoopGroup以处理客户端连接
        bossGroup = new NioEventLoopGroup(1); // 用于接受连接
        workerGroup = new NioEventLoopGroup(); // 用于处理已经被接受的连接
        ServerBootstrap b = new ServerBootstrap(); // 创建ServerBootstrap实例
        b.group(bossGroup, workerGroup) // 设置EventLoopGroup
                .channel(NioServerSocketChannel.class) // 使用NioServerSocketChannel作为服务端通道实现
                .childHandler(new ChannelInitializer<SocketChannel>() { // 设置通道的ChannelHandler链初始化器
                    @Override
                    public void initChannel(SocketChannel ch) throws Exception {
                        ChannelPipeline p = ch.pipeline();
                        // 心跳：读空闲 40 分钟
//                        p.addLast(new IdleStateHandler(40, 0, 0, TimeUnit.MINUTES));
//                        p.addLast(new LineBasedFrameDecoder(1024));
//                        p.addLast(new StringDecoder()); // 添加解码器，将ByteBuf转换为String
//                        p.addLast(new StringEncoder()); // 添加编码器，将String转换为ByteBuf发送给客户端
                        p.addLast(new ServerHandler()); // 添加自定义的处理器
                    }
                })
                .option(ChannelOption.SO_BACKLOG, 2048) // 设置TCP参数，如SO_BACKLOG等（此处为示例）
                .childOption(ChannelOption.SO_KEEPALIVE, true); // 设置保持活动连接状态选项（此处为示例）

        // 绑定端口并开始接收进来的连接，调用sync()方法阻塞等待直到绑定完成。
        ChannelFuture f = b.bind(port).sync();
        log.info("TCP 服务已启动，端口: {}" , port);
        // 等待服务器socket关闭，在调用join()之后，所有I/O操作都将关闭。
        channel = f.channel();
        channel.closeFuture().sync();
    }

    public void stop() {

        try {
            log.info("Server 关闭连接！");
            workerGroup.shutdownGracefully(); // 关闭EventLoopGroup，释放所有资源。
            bossGroup.shutdownGracefully();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void start(String host, int port, ApplicationArguments args) throws Exception {
        start(port);
    }

    public ChannelOutboundInvoker getChannel() {
        return channel;
    }

    /**
     * 指定目标地址发生数据
     * @param targetHost
     * @param value
     * @return
     */
    public boolean send(String targetHost, String value) {
        Channel channel = ipTables.get(targetHost);
        if(channel == null){
            return false;
        }
        try {
            channel.writeAndFlush(Unpooled.copiedBuffer(HexUtils.fromHexString(value)));
        }catch (Throwable ex){
            channel.writeAndFlush(Unpooled.copiedBuffer(value, CharsetUtil.UTF_8));
        }
        return true;
    }

    public class ServerHandler extends SimpleChannelInboundHandler<ByteBuf> {

        @Override
        protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {


            log.debug("收到客户端 {} 数据: {}", ctx.channel().remoteAddress(), HexUtils.toHexString(ByteBufUtil.getBytes(msg)));
            //ctx.writeAndFlush("ok\n");
        }

        // 客户端连接时触发
        @Override
        public void channelActive(ChannelHandlerContext ctx) {
            Channel channel = ctx.channel();
            InetSocketAddress inetSocketAddress = (InetSocketAddress) channel.remoteAddress();
           log.debug("客户端连接建立: {}" , inetSocketAddress);

            ipTables.put(inetSocketAddress.getHostString(), ctx.channel());
            // 可以在这里保存channel到管理类
            //ChannelManager.addChannel(channel);
        }

        // 客户端断开时触发
        @Override
        public void channelInactive(ChannelHandlerContext ctx) {
            Channel channel = ctx.channel();
            log.debug("客户端断开连接: {}" , channel.remoteAddress());
            InetSocketAddress inetSocketAddress = (InetSocketAddress) channel.remoteAddress();
            ipTables.remove(inetSocketAddress.getHostString());
            // 从管理类移除
            //ChannelManager.removeChannel(channel);
        }

        // 异常处理
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
            log.debug("客户端连接异常: {}" , cause.getMessage());
            ctx.close();
        }
    }

    public Set getIpTables() {
        return ipTables.keySet();
    }
}
